import pandas as pd
import numpy as np
from sklearn.decomposition import PCA  # 主成分分析库
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA  # 线性判别分析库
import matplotlib.pyplot as plt  # 绘图库

def load_data(url, columns):
    """加载数据集，并返回指定列名的数据"""
    try:
        # 使用pandas读取CSV文件，header=None表示没有标题行，names参数用来命名列
        data = pd.read_csv(url, header=None, names=columns)
    except Exception as e:
        # 捕获异常并打印错误信息
        print(f"加载数据时出错: {e}")
        return None
    return data

def plot_reduction(X_reduced, y, title, labels=('第一主成分', '第二主成分')):
    """绘制降维后的数据散点图"""
    plt.figure(figsize=(8, 6))
    # 根据降维后的数据绘制散点图，如果是一维则y轴全部设为0
    scatter = plt.scatter(X_reduced[:, 0], X_reduced[:, 1] if X_reduced.shape[1] > 1 else [0]*len(X_reduced),
                          c=y, cmap='viridis', edgecolor='k', s=50)
    plt.title(title)  # 设置图表标题
    plt.xlabel(labels[0])  # 设置x轴标签
    plt.ylabel(labels[1])  # 设置y轴标签
    plt.colorbar(scatter, label='类别标签')  # 添加颜色条并设置标签
    plt.grid()  # 显示网格线
    plt.show()

# 加载红酒数据集
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data"
columns = ['Class', 'Alcohol', 'Malic_acid', 'Ash', 'Alcalinity_of_ash', 'Magnesium',
           'Total_phenols', 'Flavanoids', 'Nonflavanoid_phenols', 'Proanthocyanins',
           'Color_intensity', 'Hue', 'OD280/OD315', 'Proline']
data = load_data(url, columns)

if data is not None:
    # 筛选类别为1和2的数据
    filtered_data = data[data['Class'].isin([1, 2])]
    X = filtered_data.iloc[:, 1:]  # 特征数据（去除类别列）
    y = filtered_data['Class']     # 类别标签

    # PCA - 将特征降维到二维
    pca = PCA(n_components=2)
    X_pca = pca.fit_transform(X)
    print("PCA将特征降维到两个维度：")
    print(X_pca)

    # 绘制PCA结果
    plot_reduction(X_pca, y, 'PCA: 特征降维到二维')

    # LDA - 将特征降维到一维（对于两类问题，LDA降维后只能为一维）
    lda = LDA(n_components=1)
    X_lda = lda.fit_transform(X, y)
    print("LDA将特征降维到一个维度：")
    print(X_lda)

    # 绘制LDA结果
    plot_reduction(X_lda, y, 'LDA: 特征降维到一维', labels=('线性判别成分', ''))